﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HAMath
{
    [Serializable]
    public class ModelVariogram : ICloneable
    {

        /// <summary>
        /// 
        /// </summary>
        /// <param name="modelType">模型类型</param>
        /// <param name="range">变程</param>
        /// <param name="nugget">块金值</param>
        /// <param name="c">拱高,基台值</param>
        public ModelVariogram(ModelType type, double range, double nugget, double c)
        {
            this.C = c;
            this.Range = range;
            this.Nugget = nugget;
            this._modelType = type;
        }


        double _range = 0;  //变程

        public double Range
        {
            get { return _range; }
            set 
            {
                if (value < 0)
                {
                    value = 0;
                }
                _range = value; 
            }
        }
        double _nugget = 0; //块金值

        public double Nugget
        {
            get { return _nugget; }
            set { _nugget = value; }
        }
        double _c = 0;      //拱高,基台值

        public double C
        {
            get { return _c; }
            set 
            {
                if (value < 0)
                {
                    value = 0;
                }
                _c = value; 
            }
        }

        string _nestedName = "模型变差函数";
        /// <summary>
        /// 名称
        /// </summary>
        public string NestedName
        {
            get { return _nestedName; }
            set { _nestedName = value; }
        }


        ModelType _modelType = ModelType.Spherical;  //采用哪个模型

        public ModelType ModelType
        {
            get { return _modelType; }
            set { _modelType = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="modeType"></param>
        /// <returns></returns>
        public double CalModelVariation(double h)
        {
            double result = 0;

            if (this.Range == 0)  //如果变程为0，结果自然为0
            {
                return result;  //直接返回
            }


            switch (this._modelType)
            {
                case ModelType.Spherical:
                    //球状模型
                    result= this.CalSphericalVariation(h);
                    break;
                case ModelType.Exponential:
                    //指数模型
                   result= this.CalExponentialVariation(h);
                    break;
                //case ModelType.Gaussian :
                //    result = this.CalGaussianVariation(h);
                //    break;
                //case ModelType.Power :
                //    result = this.CalPowerVariation(h);
                //    break;
            }

            return result;
        }

        /// <summary>
        /// 球状模型 
        /// </summary>
        /// <param name="h">h必须是大于等于0的值</param>
        /// <returns></returns>
        public double CalSphericalVariation(double h)
        {
            double C0 = this.Nugget + this.C;

            double result = 0;

            if (h == 0)
            {
                result = this.Nugget;
            }
            else if (h < this.Range)
            {
                result = this.Nugget + this.C * (1.5 * h / this.Range - 0.5 * Math.Pow(h / this.Range, 3));

            }
            else if (h >= this.Range)
            {
                result = this.Nugget + this.C;
            }

            result = C0 - result;

            return result;
        }

        /// <summary>
        /// 指数模型
        /// </summary>
        /// <param name="h"></param>
        /// <returns></returns>
        public double CalExponentialVariation(double h)
        {
            double C0 = this.Nugget + this.C;
            double result = 0;
            if (h == 0)
            {
                result = this.Nugget;
            }
            else if (h<this .Range )
            {
                result = this.Nugget + this.C * (1 - Math.Exp(-3 * h / this.Range));
            }
            else if (h >= this.Range)
            {
                result = this.Nugget + this.C;
            }

            result = C0 - result;

            return result;
        }


        /// <summary>
        /// 高斯模型
        /// </summary>
        /// <param name="h"></param>
        /// <returns></returns>
        public double CalGaussianVariation(double h)
        {
            double C0 = this.Nugget + this.C;

            double result = 0;

            if (h == 0)
            {
                result = this.Nugget;
            }
            else if (h < this.Range)
            {
                result = this.Nugget + this.C * (1 - Math.Exp(-3 * h * h / this.Range / this.Range));

            }
            else if (h >= this.Range)
            {
                result = this.Nugget + this.C;
            }

            result = C0 - result;

            return result;
        }


        /// <summary>
        /// 幂函数模型
        /// </summary>
        /// <param name="h"></param>
        /// <returns></returns>
        public double CalPowerVariation(double h)
        {
            double result = 0;

            if (this.Range < 0 || this.Range > 2) return 0; //这个幂函数模型是一个特殊的存在，它的变程是在0-2中间。。。要在窗体上加限制

            double C0 = this.Nugget + this.C;

            if (h == 0)
            {
                result = this.Nugget;
            }
            else 
            {
                result = this.Nugget + this.C * Math.Pow(h, this.Range);
            }

            result = C0 - result;

            return result;
        }


        public object Clone()
        {
            return this.MemberwiseClone();
        }

    }
}
